package com.rattsoftware.client.views;

import java.util.ArrayList;
import java.util.List;

import com.extjs.gxt.ui.client.Registry;
import com.extjs.gxt.ui.client.Style.LayoutRegion;
import com.extjs.gxt.ui.client.Style.SortDir;
import com.extjs.gxt.ui.client.data.BasePagingLoadConfig;
import com.extjs.gxt.ui.client.data.BasePagingLoader;
import com.extjs.gxt.ui.client.data.PagingLoadConfig;
import com.extjs.gxt.ui.client.data.PagingLoadResult;
import com.extjs.gxt.ui.client.data.PagingLoader;
import com.extjs.gxt.ui.client.data.RpcProxy;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.ComponentEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.MessageBoxEvent;
import com.extjs.gxt.ui.client.mvc.AppEvent;
import com.extjs.gxt.ui.client.mvc.Controller;
import com.extjs.gxt.ui.client.mvc.Dispatcher;
import com.extjs.gxt.ui.client.mvc.View;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.util.IconHelper;
import com.extjs.gxt.ui.client.widget.Component;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.MessageBox;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.layout.BorderLayout;
import com.extjs.gxt.ui.client.widget.layout.BorderLayoutData;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.rattsoftware.client.AppMessages;
import com.rattsoftware.client.Refreshable;
import com.rattsoftware.client.RefreshableEvent;
import com.rattsoftware.client.webclient;
import com.rattsoftware.client.controllers.CourseController;
import com.rattsoftware.client.events.AppEvents;
import com.rattsoftware.client.model.CourseSummary;
import com.rattsoftware.client.util.ProgressIndicator;
import com.rattsoftware.client.widgets.RemoteStoreFilterField;
import com.rattsoftware.client.widgets.SearchPagingToolBar;
import com.rattsoftware.server.admin.model.Course;
import com.rattsoftware.server.admin.model.User;
import com.rattsoftware.server.admin.model.exceptions.RattsParsingException;

public class CourseView extends View implements Refreshable {

	final AppMessages appMessages = GWT.create(AppMessages.class);
	private ContentPanel courseView;
	private LayoutContainer container;
	public static final int PAGE_SIZE = 10;

	Button newButton, editButton, deleteButton, newCourseUnit, viewCourseUnits;

	private Grid<CourseSummary> grid;
	private ColumnModel cm;
	SearchPagingToolBar<CourseSummary> toolBar;
	private PagingLoader<PagingLoadResult<CourseSummary>> loader;

	private List<CourseSummary> allCourseSummaries = new ArrayList<CourseSummary>();
	private User loggedInUser;

	public CourseView(Controller controller) {
		super(controller);
	}

	@Override
	protected void handleEvent(AppEvent event) {
		if (event.getType() == AppEvents.Init) {
			GWT.log("Handling Init Event in CourseView");
			initUI();
		} else if (event.getType() == AppEvents.CourseView) {
			GWT.log("Handling CourseView Event in CourseView");
			LayoutContainer wrapper = (LayoutContainer) Registry
					.get(MainAppView.CENTER_PANEL);
			wrapper.removeAll();
			wrapper.add(container);
			wrapper.layout();
			return;
		}
	}

	protected void initUI() {
		courseView = new ContentPanel();
		courseView.setHeading("Course Management");
		courseView.setAnimCollapse(false);
		courseView.addListener(Events.Expand, new Listener<ComponentEvent>() {
			public void handleEvent(ComponentEvent be) {
				Dispatcher.get().dispatch(AppEvents.CourseView);
			}
		});

		ContentPanel west = (ContentPanel) Registry.get(MainAppView.WEST_PANEL);
		west.add(courseView);
	}

	@Override
	protected void initialize() {

		container = new LayoutContainer();

		GWT.log("CourseView : initialize");
		ProgressIndicator.showProgressBar();

		List<ColumnConfig> configs = new ArrayList<ColumnConfig>();
		configs.add(new ColumnConfig("courseId", appMessages.id(), 20));
		configs.add(new ColumnConfig("courseName", appMessages.courseName(),
				100));
		configs
				.add(new ColumnConfig("shortName", appMessages.shortName(), 100));
		configs.add(new ColumnConfig("courseDescription", appMessages
				.courseDescription(), 175));
		configs.add(new ColumnConfig("noOfCourseUnits", appMessages
				.noOfCourseUnits(), 175));
		configs.add(new ColumnConfig("noOfSemester", appMessages
				.noOfSemesters(), 100));
		configs.add(new ColumnConfig("courseType", appMessages.courseType(),
				175));
		configs.add(new ColumnConfig("departmentName", appMessages
				.departmentName(), 250));

		cm = new ColumnModel(configs);
		cm.setHidden(0, true); // hide ID column

		toolBar = new SearchPagingToolBar<CourseSummary>(PAGE_SIZE);

		loader = new BasePagingLoader<PagingLoadResult<CourseSummary>>(
				new RpcProxy<PagingLoadResult<CourseSummary>>() {
					@Override
					public void load(
							Object loadConfig,
							final AsyncCallback<PagingLoadResult<CourseSummary>> callback) {
						ProgressIndicator.showProgressBar();
						final PagingLoadConfig pagingLoadConfig = (PagingLoadConfig) loadConfig;
						if (pagingLoadConfig.getSortField() == null
								|| pagingLoadConfig.getSortField().trim()
										.equals("")) {
							pagingLoadConfig.setSortField("name");
							pagingLoadConfig.setSortDir(SortDir.ASC);
						}
						pagingLoadConfig.set(RemoteStoreFilterField.PARM_FIELD,
								"name");
						pagingLoadConfig.set(RemoteStoreFilterField.PARM_QUERY,
								toolBar.getSearchFilterValue());
						GWT.log("CourseView RpcProxy:load loadConfig pageSize="
								+ pagingLoadConfig.getLimit() + " sortField="
								+ pagingLoadConfig.getSortField() + " filter="
								+ toolBar.getSearchFilterValue());
						Scheduler.get().scheduleDeferred(
								new ScheduledCommand() {
									@Override
									public void execute() {
										final CourseController controller = (CourseController) CourseView.this
												.getController();
										try {
											controller.getCourses(
													pagingLoadConfig, callback);
										} catch (RattsParsingException e) {
											e.printStackTrace();
										}
									}
								});
					}
				});

		loader.setRemoteSort(true);
		toolBar.bind(loader);

		ListStore<CourseSummary> store = new ListStore<CourseSummary>(loader);
		grid = new Grid<CourseSummary>(store, cm);
		grid.setAutoExpandColumn("courseName");
		grid.setAutoExpandMax(10000);
		grid.setStripeRows(true);
		grid.setBorders(true);

		// new
		newButton = new Button(appMessages.newCourse());
		newButton.setIcon(IconHelper.createStyle("add"));
		newButton.addListener(Events.Select, new Listener<ButtonEvent>() {
			@Override
			public void handleEvent(ButtonEvent be) {
				addNewCourse();
			}
		});

		// edit
		editButton = new Button(appMessages.editCourse());
		editButton.setIcon(IconHelper.createStyle("edit"));
		editButton.addListener(Events.Select, new Listener<ButtonEvent>() {
			@Override
			public void handleEvent(ButtonEvent be) {
				editCourse();
			}
		});

		// delete
		deleteButton = new Button(appMessages.deleteCourse());
		deleteButton.setIcon(IconHelper.createStyle("delete"));
		deleteButton.addListener(Events.Select, new Listener<ButtonEvent>() {
			@Override
			public void handleEvent(ButtonEvent be) {
				deleteCourse();
			}
		});

		// new course unit
		newCourseUnit = new Button(appMessages.newCourseUnit());
		newCourseUnit.setIcon(IconHelper.createStyle("add"));
		newCourseUnit.addListener(Events.Select, new Listener<ButtonEvent>() {
			@Override
			public void handleEvent(ButtonEvent be) {
				newCourseUnit();
			}
		});

		// view course units
		viewCourseUnits = new Button(appMessages.viewCourseUnits());
		viewCourseUnits.setIcon(IconHelper.createStyle("view"));
		viewCourseUnits.addListener(Events.Select, new Listener<ButtonEvent>() {
			@Override
			public void handleEvent(ButtonEvent be) {
				showCourseUnits();
			}
		});

		checkLoggedInUserPermissions();

		ToolBar toolBar = new ToolBar();
		toolBar.setSpacing(10);
		toolBar.add(newButton);
		toolBar.add(editButton);
		toolBar.add(deleteButton);
		toolBar.add(newCourseUnit);
		toolBar.add(viewCourseUnits);

		Scheduler.get().scheduleDeferred(new ScheduledCommand() {
			@Override
			public void execute() {
				// load the first set of data
				PagingLoadConfig config = new BasePagingLoadConfig(0, PAGE_SIZE);
				loader.load(config);
			}
		});

		getView(appMessages.registeredCourses(), grid, toolBar);
	}

	private void showCourseUnits() {
		CourseSummary summary = grid.getSelectionModel().getSelectedItem();
		if (summary != null) {
			if (!summary.getNoOfCourseUnits().equals("0")) {
				ProgressIndicator.showProgressBar();
				Scheduler.get().scheduleDeferred(new ScheduledCommand() {
					@Override
					public void execute() {
						CourseSummary summary = grid.getSelectionModel()
								.getSelectedItem();
						CourseController controller = (CourseController) getController();
						controller.forwardToViewCourseUnitController(summary);
					}
				});
			} else {
				MessageBox.alert(appMessages.listOfCourses(), appMessages
						.noCourseUnits(), null);
				ProgressIndicator.hideProgressBar();
			}
		} else {
			MessageBox.alert(appMessages.listOfCourses(), appMessages
					.courseNotSelected(), null);
		}
	}

	private void newCourseUnit() {
		ProgressIndicator.showProgressBar();
		CourseSummary summary = grid.getSelectionModel().getSelectedItem();
		if (summary != null) {
			Scheduler.get().scheduleDeferred(new ScheduledCommand() {
				@Override
				public void execute() {
					CourseSummary summary = grid.getSelectionModel()
							.getSelectedItem();
					CourseController controller = (CourseController) getController();
					controller.forwardToNewCourseUnitController(summary);
				}
			});
		} else {
			MessageBox.alert(appMessages.listOfCourses(), appMessages
					.courseNotSelected(), null);
			ProgressIndicator.hideProgressBar();
		}
	}

	private void addNewCourse() {
		ProgressIndicator.showProgressBar();
		Scheduler.get().scheduleDeferred(new ScheduledCommand() {
			@Override
			public void execute() {
				CourseController controller = (CourseController) getController();
				controller.forwardToNewCourseController();
			}
		});
	}

	private void deleteCourse() {

		// listener for message box events.
		final Listener<MessageBoxEvent> messageBoxListener = new Listener<MessageBoxEvent>() {
			@Override
			public void handleEvent(MessageBoxEvent be) {
				Button btn = be.getButtonClicked();

				if (btn.getText().equalsIgnoreCase("OK")) {
					ProgressIndicator.showProgressBar();
					Scheduler.get().scheduleDeferred(new ScheduledCommand() {
						@Override
						public void execute() {
							CourseSummary courseSummary = grid
									.getSelectionModel().getSelectedItem();
							CourseController controller = (CourseController) getController();
							// controller.forwardToEditWizard(userSummary);
						}
					});
				}
			}
		};

		if (grid.getSelectionModel().getSelectedItem() != null) {
			MessageBox.confirm(appMessages.confirm(), appMessages
					.confirmCourseDelete(), messageBoxListener);

		} else {
			MessageBox.alert(appMessages.registeredCourses(), appMessages
					.courseNotSelected(), null);
		}
	}

	private void editCourse() {
		if (grid.getSelectionModel().getSelectedItem() != null) {
			ProgressIndicator.showProgressBar();
			Scheduler.get().scheduleDeferred(new ScheduledCommand() {
				@Override
				public void execute() {
					CourseSummary courseSummary = grid.getSelectionModel()
							.getSelectedItem();
					CourseController controller = (CourseController) getController();
					controller.forwardToEditCourseController(courseSummary);
				}
			});
		} else {
			MessageBox.alert(appMessages.registeredCourses(), appMessages
					.courseNotSelected(), null);
		}
	}

	public void setAllCourseSummaries(List<CourseSummary> courseSummary) {
		this.allCourseSummaries = courseSummary;
	}

	@Override
	public void refresh(RefreshableEvent event) {
		GWT.log("Refreshing...");
		if (event.getEventType() == RefreshableEvent.Type.UPDATE_COURSE) {
			Course course = event.getData();
			ListStore<CourseSummary> store = grid.getStore();
			CourseSummary summary = getCourseSummary(course.getId());
			if (summary != null) {
				summary.updateCourseSummary(course);
				store.update(summary);
			}
		} else if (event.getEventType() == RefreshableEvent.Type.CREATE_COURSE) {
			Course course = event.getData();
			ListStore<CourseSummary> store = grid.getStore();
			CourseSummary summary = new CourseSummary(course);
			store.add(summary);
		} else if (event.getEventType() == RefreshableEvent.Type.REFRESH_COURSE_LIST) {
			toolBar.refresh();
		}
	}

	CourseSummary getCourseSummary(String userId) {
		String userIdStr = String.valueOf(userId);
		for (CourseSummary userSummary : grid.getStore().getModels()) {
			if (userIdStr.equals(userSummary.getId())) {
				return userSummary;
			}
		}
		GWT.log("ERROR: no user summary found id=" + userId);
		return null;
	}

	private void getView(String title, Component component,
			Component topComponent) {
		GWT.log("CourseView : Initialising Window");

		BorderLayout layout = new BorderLayout();
		layout.setEnableState(false);
		container.setLayout(layout);

		ContentPanel cp = new ContentPanel();
		cp.setLayout(new FitLayout());
		cp.setHeading("Course Management");
		cp.setBorders(false);
		cp.add(component);
		cp.setBottomComponent(toolBar);
		cp.setTopComponent(topComponent);

		container.add(cp, new BorderLayoutData(LayoutRegion.CENTER));
	}

	private User getLoggedInUser() {
		if (loggedInUser == null) {
			loggedInUser = Registry.get(webclient.LOGGED_IN_USER_NAME);
		}
		return loggedInUser;
	}

	private void checkLoggedInUserPermissions() {
		if (getLoggedInUser() == null) {
			GWT
					.log("Could not find logged in user, so could not determine permissions");
			return;
		}
		// if (loggedInUser.hasPermission(Permission.PERM_ADD_COURSE)) {
		newButton.show();
		// }
		// if (loggedInUser.hasPermission(Permission.PERM_EDIT_COURSE)) {
		editButton.show();
		// }
		// if (loggedInUser.hasPermission(Permission.PERM_VIEW_COURSE)) {
		viewCourseUnits.show();
		// }
		// if (loggedInUser.hasPermission(Permission.PERM_DELETE_COURSE)) {
		deleteButton.show();
		// }
	}
}